// 游戏控制类 所有其他类都在这里处理
// 引入其他类
import Food from "./Food"
import Snake from './Snake'
import ScorePanel from "./ScorePanel"

class GameControl {
  // 食物
  food: Food
  // 蛇
  snake: Snake
  // 记分牌
  scorePanel: ScorePanel

  // 创建一个属性来存储蛇的移动方向(也就是按键方向) 
  direction: string = ''
  // 记录蛇是否或者
  isLive = true

  constructor() {
    this.food = new Food()
    this.snake = new Snake()
    this.scorePanel = new ScorePanel()
    // 一创建实例就初始
    this.init()
  }

  // 游戏初始化 调用后游戏立马开始
  init() {
    //注意奥改变this指向 必须指挥GameControl实例对象
    document.addEventListener('keydown', this.keydownHandler.bind(this))
    // 调用蛇移动
    this.run()
  }

  // ArrowDown ie->Down
  // ArrowRight Right
  // ArrowLeft  Left
  // ArrowUp Up
  // 创建一个按键按下的响应函数
  keydownHandler(event: KeyboardEvent) {
    // 需要检测event.key的值是否合法(用户是否按下了正确的方向键)
    // 修改direction属性
    this.direction = event.key
  }

  // 创建一个控制蛇移动的方法
  run() {
    /*
    根据方向(this.direction)来使蛇的位置改变
    向上： top 减少
    向下： top 增加
    向左： left 减少
    向右： left 增加
    */
    // 获取蛇坐标
    let X = this.snake.X
    let Y = this.snake.Y

    // 根据按下的方向修改XY值
    switch (this.direction) {
      case 'ArrowUp':
      case 'Up':
        Y -= 10
        break;
      case 'ArrowDown':
      case 'Down':
        Y += 10
        break;
      case 'ArrowLeft':
      case 'Left':
        X -= 10
        break;
      case 'ArrowRight':
      case 'Right':
        X += 10
        break;
    }

    // 检测是否迟到食物
    this.checkEat(X, Y)


    // 修改蛇坐标X和Y值
    try {
      this.snake.X = X
      this.snake.Y = Y
    } catch (error) {
      alert(error.message)
      // 宣判蛇的死刑
      this.isLive = false
    }

    // 蛇活着才开启定时器 递归 通过this调用方法名一般都要bind绑定回原实例对象
    this.isLive && setTimeout(this.run.bind(this), 300 - (this.scorePanel.level - 1) * 30);
  }

  // 是否吃到食物
  checkEat(X: number, Y: number) {
    // 吃到实物了
    if (this.food.X === X && this.food.Y === Y) {
      // 食物坐标改变
      this.food.change()
      // 记分牌加一分
      this.scorePanel.addScore()
      // 蛇增加一节
      this.snake.addBody()
    }
  }
}

export default GameControl